json-server 进阶:Whitelist 白名单模式与生产接口 Proxy 功能
本节在 json-server 基础 Mock 之上,实现 Whitelist 白名单机制和 Proxy 代理转发功能。当请求接口在白名单中时,自动将请求转发到真实的生产服务器。
Whitelist 设计思路
Whitelist 的核心逻辑:
客户端请求 → Whitelist 检查
├── 匹配白名单 → 代理转发到生产服务器
└── 不在白名单中 → json-server Mock 响应
text
URL Rewrite 配置
首先需要将所有 /api/* 的请求重写到对应的资源路径:
// server.js
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()
server.use(middlewares)
// URL 重写:/api/home → /home
server.use(jsonServer.rewriter({
'/api/*': '/$1'
}))
server.use(router)
server.listen(3000, () => {
console.log('JSON Server is running')
})
javascript
在 db.json 中添加测试数据:
{
"home": [
{ "id": 1, "message": "hello from mock" }
]
}
json
测试 rewrite:GET http://localhost:3000/api/home 正常返回数据。
安装代理中间件
rewrite 只能在当前服务器内部做路径切换,不能跨服务器转发。跨服务器转发需要使用 http-proxy-middleware:
pnpm install http-proxy-middleware
bash
实现白名单 + 代理转发
const jsonServer = require('json-server')
const { createProxyMiddleware } = require('http-proxy-middleware')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()
// 生产服务器地址
const testServer = 'http://localhost:3030'
// 白名单配置(硬编码方式)
const whitelist = [
{ url: 'home', type: 'get' }
]
server.use(middlewares)
// URL 重写
server.use(jsonServer.rewriter({
'/api/*': '/$1'
}))
// 白名单中间件
server.use((req, res, next) => {
const isWhitelisted = whitelist.some(item => {
const methodMatch = req.method.toLowerCase() === item.type.toLowerCase()
const urlMatch = req.url.replace('/api/', '') === item.url
return methodMatch && urlMatch
})
if (isWhitelisted) {
createProxyMiddleware({
target: testServer,
changeOrigin: true
})(req, res, next)
} else {
next()
}
})
server.use(router)
server.listen(3000, () => {
console.log('JSON Server is running')
})
javascript
创建目标服务器
创建第二个 json-server 模拟生产环境:
// server1.js
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db1.json')
const middlewares = jsonServer.defaults()
server.use(middlewares)
// 使用 prefix 而非 rewrite
server.use(jsonServer.rewriter({
'/api/*': '/$1'
}))
server.use(router)
server.listen(3030, () => {
console.log('JSON Server 1 running on port 3030')
})
javascript
// db1.json
{
"home": [
{ "id": 1, "message": "from localhost 3030" }
]
}
json
// package.json
{
"scripts": {
"dev": "nodemon server.js",
"dev:server1": "nodemon server1.js"
}
}
json
问题排查
1. 方法名大小写
Express 的 req.method 返回大写(GET),而配置中可能是小写(get):
// 需要统一转小写
req.method.toLowerCase() === item.type.toLowerCase()
javascript
2. URL 路径匹配
rewrite 后 URL 不包含 /api 前缀(因为 rewrite 已经去掉了),但目标服务器需要前缀:
createProxyMiddleware({
target: testServer,
changeOrigin: true,
pathRewrite: { '^/': '/api/' } // 加回 /api 前缀
})(req, res, next)
javascript
关键点:rewrite 是 json-server 内部的路径转换,proxy 到另一台服务器时需要考虑目标服务器的路径规范。
动态白名单:通过接口管理
将白名单数据存储在 db.json 中,通过 RESTful 接口动态管理。
1. 修改 db.json
{
"whitelist": [
{ "id": 1, "url": "home", "type": "get" }
],
"hello": [
{ "id": 1, "message": "hello world" }
],
"home": [
{ "id": 1, "message": "from mock server" }
]
}
json
2. 修改 server.js 读取动态白名单
server.use((req, res, next) => {
// 从 db.json 中读取白名单
const whitelist = router.db.get('whitelist').value()
const isWhitelisted = whitelist.some(item => {
const methodMatch = req.method.toLowerCase() === item.method.toLowerCase()
const urlMatch = req.url.replace('/api/', '') === item.url
return methodMatch && urlMatch
})
if (isWhitelisted) {
createProxyMiddleware({
target: testServer,
changeOrigin: true,
pathRewrite: { '^/': '/api/' }
})(req, res, next)
} else {
next()
}
})
javascript
3. 通过接口管理白名单
# 查看当前白名单
GET http://localhost:3000/whitelist
# 添加白名单规则
POST http://localhost:3000/whitelist
Content-Type: application/json
{ "url": "test", "method": "get" }
# 删除白名单规则
DELETE http://localhost:3000/whitelist/2
bash
添加白名单后,对应接口会代理到真实服务器;删除后回到 Mock 响应。
完整架构流程
客户端请求 (http://localhost:3000)
│
├─ URL Rewrite (/api/* → /*)
│
├─ Whitelist 检查(从 db.json 读取)
│ ├─ 匹配 → Proxy 到 http://localhost:3030
│ └─ 不匹配 → 继续
│
├─ 自定义分页参数转换
│
└─ json-server 路由处理(Mock 响应)
text
这种架构在实际开发中非常实用:
- 开发阶段:大部分接口走 Mock,个别接口需要对接真实服务时加入白名单
- 联调阶段:逐步将接口从 Mock 切换到真实服务,通过白名单管理切换
- 测试阶段:可以灵活控制哪些接口走 Mock,哪些走真实服务
↑